﻿using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using VOL.Core.DBManager;
using VOL.Core.Extensions;
using VOL.Core.ManageUser;
using VOL.Core.Utilities;
using VOL.Entity.DomainModels;

namespace VOL.Core.Float
{
/// <summary>
/// 自定义流程工具
/// </summary>
    public static class FloatManager
    {

        /// <summary>
        /// 启动流程
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="changeTableStatus"></param>
        public static void AddProcese<T>(T entity) where T : class
        {
            string reimtable = typeof(T).GetEntityTableName();
            //any相当于使用SQL中的exist语句，注意使用any时不能toList();
            var fl_template_ls = DBServerProvider.DbContext.Set<fl_template>().AsQueryable();//此处不能使用toList(),否则Linq报错
            List<fl_template_list> fl_template_list_list = DBServerProvider.DbContext.Set<fl_template_list>()
                .Where(w => fl_template_ls.Any(c => c.ft_id == w.ft_id && c.ft_table == reimtable)).ToList();

            var userInfo = UserContext.Current.UserInfo;
            for (int i = 0; i < fl_template_list_list.Count; i++)//从模版中取流程数据
            {
                var tt = fl_template_list_list[i];
                fk_reimfloat frf = new fk_reimfloat()
                {
                    //username = tt.bek==0?userInfo.UserName:"",//只流程第一步
                    //userrealname = tt.bek == 0 ? userInfo.UserTrueName:"",
                    //bdatetime = tt.bek == 0 ? DateTime.Now:null,
                    stepid = tt.stepid,
                    stepname = tt.stepname,
                    reyijian = (tt.bek == 0 ? "处理中" : ""),
                    reimid = typeof(T).GetKeyProperty().GetValue(entity).ToGuid(),//业务表的KEY值
                    reimtable = reimtable,
                    bek = tt.bek,
                    nextstepid = tt.nextstepid,
                    pxm = tt.pxm,
                    tjsql = tt.tjsql,
                    roleid = tt.roleid,
                    path_router = tt.path_router
                };
                if (tt.bek == 0)//流程起点
                {
                    fk_reimfloat_his frf_his = new fk_reimfloat_his()
                    {
                        username = userInfo.UserName,
                        userrealname = userInfo.UserTrueName,
                        bdatetime = DateTime.Now,
                        stepid = tt.stepid,
                        stepname = tt.stepname,
                        reyijian = "",
                        remark = "启动流程",//意见详情
                        reimid = typeof(T).GetKeyProperty().GetValue(entity).ToGuid(),//业务表的KEY值
                        reimtable = reimtable,
                        bek = tt.bek,
                        nextstepid = tt.nextstepid,
                        pxm = tt.pxm,
                        tjsql = tt.tjsql,
                        roleid = tt.roleid,
                        path_router = tt.path_router
                    };
                    DBServerProvider.DbContext.Set<fk_reimfloat_his>().Add(frf_his);

                }


                DBServerProvider.DbContext.Set<fk_reimfloat>().Add(frf);
            }

            PropertyInfo stepidProperty = typeof(T).GetProperty("stepid");
            stepidProperty.SetValue(entity, GetFirstStepid<T>(entity));
            DBServerProvider.DbContext.Update(entity);
            DBServerProvider.DbContext.SaveChanges();
            new_task(entity, (int)fl_template_list_list.Where(w => w.bek == 0).Select(s => s.stepid).FirstOrDefault(),"创建任务");//启动任务 
        }

        /// <summary>
        /// 审核\回退到指定的步骤：
        ///       1、完成任务,把任务标记为1；
        ///       2、删除当前步骤所有没有完成的任务；
        ///       3、把审核意见写入fk_reimfloat当前步骤行；
        ///       4、fk_reimfloat中nextstepid写入“处理中”
        ///       5、产生的任务；
        ///       
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="entity"></param>
        /// <param name="status"></param>
        /// <param name="remark"></param>
        /// <param name="tostepid">到达的步骤号</param>
        public static void Audit_To_Stepid<T>(T entity, string remark,int tostepid) where T : class
        {
            var dbContext = DBServerProvider.DbContext;
            var query = dbContext.Set<T>();
            var userInfo = UserContext.Current.UserInfo;
            var keyProperty = typeof(T).GetKeyProperty();
            string key = keyProperty.GetValue(entity).ToString();//业务表key值
            string workTable = typeof(T).GetEntityTableName();//业务表
            int curr_stepid = Convert.ToInt16(typeof(T).GetProperty("stepid").GetValue(entity));//当前步骤号
            //0、完成当前任务
            fk_reimtask frt = dbContext.Set<fk_reimtask>().Where(w => w.stepid == curr_stepid && w.reimid == key.ToGuid() && w.to_username == userInfo.UserName && w.ishandled != 1).FirstOrDefault();//完成当前任务
            if (frt != null)
            {
                
                frt.ishandled = 1;
               /* if (tostepid == 90)
                {
                    frt.ishandled = 0;
                }*/
                frt.handledtime = DateTime.Now;
                frt.reyijian = "回退处理";
                frt.remark = remark;
                
                dbContext.Set<fk_reimtask>().Update(frt);
                dbContext.SaveChanges();
            }
            
            //1、把审核意见写入fk_reimfloat当前步骤行；
            fk_reimfloat ff = new fk_reimfloat();
            dbContext.Entry(ff).State = EntityState.Detached;
            ff = dbContext.Set<fk_reimfloat>().Where(w => w.stepid == curr_stepid && w.reimid == key.ToGuid()).FirstOrDefault();
            ff.remark = remark;
            ff.reyijian = "回退处理";//同意or不同意
            ff.bdatetime = DateTime.Now;
            ff.username = userInfo.UserName;//回退用户处理，区别正常提交，为了回退后可以正常提交
            //ff.username = userInfo.UserName + "00";//回退用户处理，区别正常提交，为了回退后可以正常提交
            ff.userrealname = userInfo.UserTrueName;
            dbContext.Update(ff);
            dbContext.SaveChanges();
            dbContext.Entry(ff).State = EntityState.Detached;//注意Detached一定要放在第一个SaveChanges之后，否则报跟踪错误
            //2、写入历史表
            fk_reimfloat_his ff_his = new fk_reimfloat_his();
            var s_type = ff.GetType();//原对象
            var to_type = typeof(fk_reimfloat_his);//目的对象
            foreach (var s in s_type.GetProperties())
            {
                foreach (var to in to_type.GetProperties())
                {
                    if (s.Name == to.Name)
                    {
                        to.SetValue(ff_his, s.GetValue(ff));//前面是目的对象，后面的原对象的值
                    }
                }
            }
            dbContext.Add(ff_his);
            dbContext.SaveChanges();
            //3、判断前端提交的status，
            //          如果同意就流转到下一节点（next）&&fk_reimfloat中nextstepid写入“处理中”
            //          如果不同意就会原始节点（pre）
            PropertyInfo stepidProperty = typeof(T).GetProperty("stepid");
            


            //fk_reimfloat ff_1 = new fk_reimfloat();
            dbContext.Entry(ff).State = EntityState.Detached;
            List<fk_reimfloat> ff_list = dbContext.Set<fk_reimfloat>().Where(w => w.stepid >= tostepid && w.reimid == key.ToGuid()).ToList();//后面所有的步骤都清空
            for (int i = 0; i < ff_list.Count; i++)//
            {
                dbContext.Entry(ff_list[i]).State = EntityState.Detached;
                if (ff_list[i].stepid== tostepid)
                {
                    ff_list[i].reyijian = "处理中";
                }
                else
                {
                    ff_list[i].reyijian = "";//下一步骤提示
                }  
                ff_list[i].bdatetime = null;
                ff_list[i].username = null;//回退用户处理，区别正常提交，为了回退后可以正常提交
                ff_list[i].remark = null;
                ff_list[i].userrealname = null;
                dbContext.Entry(ff_list[i]).State = EntityState.Detached;
                dbContext.Update(ff_list[i]);
            }
            //删除当前步骤没有审核的task
            var del_task = dbContext.Set<fk_reimtask>().Where(w => w.stepid == curr_stepid && w.reimid == key.ToGuid() && w.ishandled != 1).ToList();
            dbContext.Set<fk_reimtask>().RemoveRange(del_task);

            new_task(entity, tostepid,"回退");//产生任务
            stepidProperty.SetValue(entity, tostepid);
            dbContext.Entry(ff).State = EntityState.Detached;
            
            query.Update(entity);//回写业务表T的nextstepid
            dbContext.SaveChanges();

        }
        /// <summary>
        /// 审核：1、完成任务,把任务标记为1；
        ///       2、把审核意见写入fk_reimfloat当前步骤行；
        ///       3、如果同意就流转到下一节点（next）&&fk_reimfloat中nextstepid写入“处理中”  
        ///       4、判断前端提交的status，如果status=="不同意" 删除当前步骤所有没有完成的任务，如果不同意就回到原始节点（pre）
        ///          4、判断前端提交的status，如果status=="同意"（判断当前步骤中是否还有其他的任务，如果还有就退出，如果没有继续（正式提交））
        ///       
        ///       5、产生新的任务；调用new_task
        ///       6、当该条流程的nextstepid为-1，且该节点所有人员都已经审核同意了，则将流程表中的step_id置为-1.
        ///          并在流程图的意见中提示 归档
        ///          在审核历史中 提示 流程终止
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="entity"></param>
        /// <param name="status"></param>
        /// <param name="remark"></param>
        public static void Audit<T>(T entity, string status, string remark) where T : class
        {
            var dbContext = DBServerProvider.DbContext;
            var query = dbContext.Set<T>();
            var userInfo = UserContext.Current.UserInfo;
            var keyProperty = typeof(T).GetKeyProperty();
            string key = keyProperty.GetValue(entity).ToString();//业务表key值
            string workTable = typeof(T).GetEntityTableName();//业务表
            int curr_stepid = Convert.ToInt16(typeof(T).GetProperty("stepid").GetValue(entity));//当前步骤号
            //0、完成当前任务
            fk_reimtask frt= dbContext.Set<fk_reimtask>().Where(w => w.stepid == curr_stepid && w.reimid == key.ToGuid() && w.to_username==userInfo.UserName && w.ishandled!=1).FirstOrDefault();//完成当前任务
            if (frt != null)
            {
                frt.ishandled = 1;
                frt.handledtime = DateTime.Now;
                frt.reyijian = status;
                frt.remark = remark;
                dbContext.Set<fk_reimtask>().Update(frt);
                dbContext.SaveChanges();
            }
            
            //1、把审核意见写入fk_reimfloat当前步骤行；
            fk_reimfloat ff = new fk_reimfloat();
            dbContext.Entry(ff).State = EntityState.Detached;
            ff = dbContext.Set<fk_reimfloat>().Where(w => w.stepid == curr_stepid && w.reimid == key.ToGuid()).FirstOrDefault();//修改当前步骤的意见
            ff.remark = remark;
            ff.reyijian = status;//同意or不同意
            ff.bdatetime=DateTime.Now;
            ff.username = userInfo.UserName;
            ff.userrealname = userInfo.UserTrueName; 
            dbContext.Update(ff);
            dbContext.SaveChanges();
            dbContext.Entry(ff).State = EntityState.Detached;//注意Detached一定要放在第一个SaveChanges之后，否则报跟踪错误
            //2、插入历史表
            fk_reimfloat_his ff_his = new fk_reimfloat_his();
            var s_type = ff.GetType();//原对象
            var to_type = typeof(fk_reimfloat_his);//目的对象
            foreach (var s in s_type.GetProperties())
            {
                foreach (var to in to_type.GetProperties())
                {
                    if (s.Name == to.Name)
                    {
                        to.SetValue(ff_his, s.GetValue(ff));//前面是目的对象，后面的原对象的值
                    }
                }
            }
            dbContext.Add(ff_his);
            dbContext.SaveChanges();
            dbContext.Entry(ff_his).State = EntityState.Detached;//注意Detached一定要放在第一个SaveChanges之后，否则报跟踪错误
            //3、判断前端提交的status，
            //          如果同意就流转到下一节点（next）&&fk_reimfloat中nextstepid写入“处理中”
            //          如果不同意就会原始节点（pre）
            //注意：提交就是把自己的任务结束，是否到下一环节需要判断本节点的所有任务全部结束会自动流转到下一步骤
            int next_stepid=get_next_step(curr_stepid, (Guid)key.ToGuid());
            int first_stepid = GetFirstStepid(entity);
            PropertyInfo stepidProperty = typeof(T).GetProperty("stepid");
            int w_co = 0;//当前步骤未完成的任务数量
            w_co = dbContext.Set<fk_reimtask>().Where(w => w.stepid == curr_stepid && w.reimid == key.ToGuid() && w.ishandled != 1).Count();

            if (next_stepid != -1)//不是最后一个节点
            {
                if (status == "同意" && w_co==0)// w_co==0只有本节点协同人员全部审核完成了，才进入下一步骤（生成新的任务）
                {
                    // 判断下一个步骤是不是归档节点。
                    //fk_reimfloat ff_1 = new fk_reimfloat();
                    dbContext.Entry(ff).State = EntityState.Detached;
                    ff = dbContext.Set<fk_reimfloat>().Where(w => w.stepid == next_stepid && w.reimid == key.ToGuid()).FirstOrDefault();//提示下一步骤“处理中”
                    // 产品定价流程中设有归档节点。再此处判断是否是归档节点。如果是归档节点自动审核
                    if (next_stepid == 99)
                    {
                        // 流程展示
                        dbContext.Entry(ff).State = EntityState.Detached;
                        ff.reyijian = "同意";//下一步骤提示
                        ff.bdatetime = DateTime.Now;//下一步骤提示清空
                        ff.username = "admin"; //下一步骤提示清空
                        ff.userrealname ="超级管理员";
                        ff.remark = "归档";

                        // 审核历史中需要展示归档节点同意并且意见为归档
                        ff_his.stepid = next_stepid;
                        ff_his.stepname = ff.stepname;
                        ff_his.username = "admin"; //操作人
                        ff_his.userrealname = "超级管理员";
                        ff_his.bdatetime = DateTime.Now;//操作时间
                        ff_his.reyijian = "同意";
                        ff_his.remark = "归档";
                        ff_his.reimid = ff.reimid;
                        ff_his.reimtable = ff.reimtable;
                        ff_his.bek = ff.bek;
                        ff_his.nextstepid = ff.nextstepid;
                        ff_his.pxm = ff.pxm;
                        ff_his.tjsql = ff.tjsql;
                        ff_his.roleid = ff.roleid;
                        ff_his.path_router = ff.path_router;
                        dbContext.Add(ff_his);
                        dbContext.SaveChanges();
                        dbContext.Entry(ff_his).State = EntityState.Detached;
                    }
                    else
                    {
                        dbContext.Entry(ff).State = EntityState.Detached;
                        ff.reyijian = "处理中";//下一步骤提示
                        ff.bdatetime =null;//下一步骤提示清空
                        ff.username = ""; //下一步骤提示清空
                        ff.remark = "";
                    }
                    //dbContext.Update(ff);
                    dbContext.Update(ff);
                    dbContext.SaveChanges();
                    new_task(entity, next_stepid,"同意");//产生任务,不进入下一步骤不产生任务（多人汇签时不产生新的任务）
                    stepidProperty.SetValue(entity, next_stepid);
                }
                if (status == "不同意")//不同意,业务表回到firststepid
                {
                    List<fk_reimfloat> ff_list = dbContext.Set<fk_reimfloat>().Where(w => w.stepid >= first_stepid && w.reimid == key.ToGuid()).ToList();//后面所有的步骤都清空
                    for (int i = 0; i < ff_list.Count; i++)//
                    {
                        dbContext.Entry(ff_list[i]).State = EntityState.Detached;
                        if (ff_list[i].stepid == first_stepid)
                        {
                            ff_list[i].reyijian = "处理中";
                        }
                        else
                        {
                            ff_list[i].reyijian = "";//下一步骤提示
                        }
                        ff_list[i].bdatetime = null;
                        ff_list[i].username = null;//回退用户处理，区别正常提交，为了回退后可以正常提交
                        ff_list[i].remark = null;
                        ff_list[i].userrealname = null;
                        dbContext.Entry(ff_list[i]).State = EntityState.Detached;
                        dbContext.Update(ff_list[i]);
                        dbContext.SaveChanges();
                    }

                   // ff = dbContext.Set<fk_reimfloat>().Where(w => w.stepid == first_stepid && w.reimid == key.ToGuid()).FirstOrDefault();
                    //ff.reyijian = "不同意";//下一步骤提示
                    //当前未处理任务
                    var del_task= dbContext.Set<fk_reimtask>().Where(w => w.stepid == curr_stepid && w.reimid == key.ToGuid() && w.ishandled != 1).ToList();
                    dbContext.Set<fk_reimtask>().RemoveRange(del_task);
                    new_task(entity, first_stepid, "不同意");//产生任务
                    stepidProperty.SetValue(entity, first_stepid);
                }
            }
            dbContext.Entry(ff).State = EntityState.Detached;
           
            query.Update(entity);//回写业务表T的nextstepid
            dbContext.SaveChanges();

        }

        /// <summary>
        /// 获取流程第一步stepid,给前端Control使用
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="entity"></param>
        /// <returns></returns>
        public static int GetFirstStepid<T>(T entity) where T : class
        {
            string reimtable = typeof(T).GetEntityTableName();
            var fl_template_ls = DBServerProvider.DbContext.Set<fl_template>().AsQueryable();//此处不能使用toList(),否则Linq报错
            int? stepid = DBServerProvider.DbContext.Set<fl_template_list>()
                .Where(w => fl_template_ls.Any(c => c.ft_id == w.ft_id && c.ft_table == reimtable) && w.bek == 0).Select(s=>s.stepid).FirstOrDefault();
            return (int)stepid;
        }

        /// <summary>
        /// 获取当前步骤的前一步骤号,如果没有返回当前步骤号
        /// </summary>
        /// <param name="curr_stepid"></param>
        /// <param name="keyvalue"></param>
        /// <returns></returns>
        public static int get_pre_step(int curr_stepid, Guid keyvalue)
        {
            int pre_stepid = curr_stepid;
            fk_reimfloat fk_reimfloat_ls = DBServerProvider.DbContext.Set<fk_reimfloat>().Where(w => w.nextstepid == curr_stepid && w.reimid == keyvalue).FirstOrDefault();
            if (fk_reimfloat_ls == null)
            {
                return pre_stepid;
            }
            else
            {
                pre_stepid = (int)fk_reimfloat_ls.stepid;
            }
            return (int)pre_stepid;  
        }
            /// <summary>
            ///-1表示流程的最后节点，返回-1，表示当前节点就是最后一个节点
            /// </summary>
            /// <param name="curr_stepid">当前stepid</param>
            /// <param name="keyvalue">业务表的keyvalue</param>
            /// <returns></returns>
            public static int get_next_step(int curr_stepid,Guid keyvalue)
        {
            fk_reimfloat fk_reimfloat_ls = DBServerProvider.DbContext.Set<fk_reimfloat>().Where(w => w.stepid == curr_stepid && w.reimid == keyvalue).FirstOrDefault();
            int nextstepid = (int)fk_reimfloat_ls.nextstepid;
            if (nextstepid == -1)//-1表示流程的最后节点，返回-1，表示当前节点就是最后一个节点
            {
                return -1;
            }
            List<fk_reimfloat> t_list = DBServerProvider.DbContext.Set<fk_reimfloat>().Where(w => w.reimid == keyvalue && w.stepid == nextstepid).ToList();
            //先获取下一步骤判断是否存在
            if (t_list.Count > 0)//说明存在下一步骤存在
            {
                while (1 == 1)
            {
                    string tsql = t_list[0].tjsql;
                    if (string.IsNullOrEmpty(tsql))
                    {
                        break;//说明没有SQL条件语句，跳出循环，直接return
                    }
                    else
                    {
                        tsql = tsql.Replace("@key_id@", keyvalue.ToString());//.Replace("@tj_je@", t_list[0].tjsql.ToString());
                        List<dynamic> rnt_list = DBServerProvider.SqlDapper.QueryList<dynamic>(tsql, "").ToList();
                        if (rnt_list.Count > 0)
                        {
                            break;//说明当前步骤要执行,满足条件跳出循环，直接return
                        }
                        return get_next_step(nextstepid, keyvalue);////递归，只有当下一步骤不存在自动退出,这里一定要return 否则就无限循环 2022年11月22日 09:59:34
                    }

            }
                return nextstepid;
            }
            else
            {
                return curr_stepid;
            }
            // return nextstepid;
        }

        /// <summary>
        /// 删除本步骤中没有审核的所有任务
        /// 应用场景，审核场景中需要增加其条件的审核人，所以先清除本步骤的任务
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="entity"></param>
        /// <param name="stepid"></param>
        public static void delete_task<T>(T entity, int stepid) where T : class
        {
            var keyProperty = typeof(T).GetKeyProperty();
            string key = keyProperty.GetValue(entity).ToString();//业务表key值
            var del_key_array = DBServerProvider.DbContext.Set<fk_reimtask>().Where(w => w.stepid == stepid && w.reimid == (Guid)key.ToGuid() && w.ishandled != 1);
            DBServerProvider.DbContext.Set<fk_reimtask>().RemoveRange(del_key_array);//清空本步骤没有审核过的任务
            DBServerProvider.DbContext.SaveChanges();
        }
        /// <summary>
        /// 向流程节点增加审核任务，单独指定人和步骤，（应用场景  增加汇签人）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="entity"></param>
        /// <param name="tostepid"></param>
        /// <param name="tousername"></param>
        public static void add_task<T>(T entity, int tostepid,string tousername,string describe) where T : class
        {
            var dbContext = DBServerProvider.DbContext;
            var query = dbContext.Set<T>();
            var userInfo = UserContext.Current.UserInfo;
            var keyProperty = typeof(T).GetKeyProperty();
            string key = keyProperty.GetValue(entity).ToString();//业务表key值
            string workTable = typeof(T).GetEntityTableName();//业务表
            
            fk_reimfloat ff = new fk_reimfloat();
            dbContext.Entry(ff).State = EntityState.Detached;
            ff = dbContext.Set<fk_reimfloat>().Where(w => w.stepid == tostepid && w.reimid == key.ToGuid()).FirstOrDefault();
            //if (ff.bek == 0 || ff.nextstepid == -1) return;//目标步骤如果是结束或在起始都不产生任务
            //if (ff.nextstepid == -1) return;//目标步骤如果是结束不产生任务
            var del_key_array = DBServerProvider.DbContext.Set<fk_reimtask>().Where(w => w.stepid == tostepid && w.reimid == (Guid)key.ToGuid() && w.ishandled != 1 &&w.to_username== tousername);
            DBServerProvider.DbContext.Set<fk_reimtask>().RemoveRange(del_key_array);//删除本人没有审核过的任务
            List<string> to_username = new List<string>();//本步骤任务领取的人员清单；
            fk_reimtask fk_Reimtask = new fk_reimtask();
            fk_Reimtask.path_router = ff.path_router;
            fk_Reimtask.menuname = DBServerProvider.DbContext.Set<Sys_Menu>().Where(w => w.Url == ff.path_router).Select(s => s.MenuName).FirstOrDefault();
            fk_Reimtask.createtime = DateTime.Now;
            fk_Reimtask.to_username = tousername;
            var user = DBServerProvider.DbContext.Set<Sys_User>().Where(w => w.UserName == tousername.Trim()).FirstOrDefault();
            fk_Reimtask.to_userrealname = user.UserTrueName; 
            if (!string.IsNullOrEmpty(user.Email)) SendEmail(user.Email, "【产品定价流程】审批提醒", describe + "【产品定价流程】<br>请即时登录系统审批!<br>链接： <a href='http://10.100.8.241:9990/#/home'>产品定价流程系统</a>"); 
            fk_Reimtask.ishandled = 0;
            fk_Reimtask.reimid = key.ToGuid();
            fk_Reimtask.stepid = tostepid;
            fk_Reimtask.stepname = ff.stepname;
            fk_Reimtask.reimtable = workTable;
            fk_Reimtask.task_type = describe;
            if (tostepid == 20 || tostepid == 70)//财务核准或者财务核价 发送邮件给艾玲
            {
                string email = "ailing3@mychery.com";//
                SendEmail(email, "【产品定价流程】审批提醒", describe + "【产品定价流程】<br>请即时登录系统审批!<br>链接： <a href='http://10.100.8.241:9990/#/home'>产品定价流程系统</a>"); 
            }
            DBServerProvider.DbContext.Add(fk_Reimtask);
            DBServerProvider.DbContext.SaveChanges();
        }
        /// <summary>
        /// 产生审批任务
        /// 1、清除目标步骤号对应的没有完成的所有任务；
        /// 
        /// 2、获取目标步骤对应流程表，主要是为给任务数据填入数据；
        /// 3、生成目标步骤对应的任务数据；（需要获取下一步骤对应角色的所有人）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="entity"></param>
        ///<param name="tostepid"></param>
        ///<param name="status">业务操作名称</param>
        public static void new_task<T>(T entity, int tostepid,string status) where T : class
        {
            var dbContext = DBServerProvider.DbContext;
            var query = dbContext.Set<T>();
            var userInfo = UserContext.Current.UserInfo;
            var keyProperty = typeof(T).GetKeyProperty();
            string key = keyProperty.GetValue(entity).ToString();//业务表key值
            string workTable = typeof(T).GetEntityTableName();//业务表
            int curr_stepid = Convert.ToInt16(typeof(T).GetProperty("stepid").GetValue(entity));//当前步骤号
            fk_reimfloat ff = new fk_reimfloat();
            dbContext.Entry(ff).State = EntityState.Detached;
            ff = dbContext.Set<fk_reimfloat>().Where(w => w.stepid == tostepid && w.reimid == key.ToGuid()).FirstOrDefault();
            //if (ff.bek == 0 || ff.nextstepid == -1) return;//目标步骤如果是结束或在起始都不产生任务
            //if (ff.nextstepid == -1) return;//目标步骤如果是结束不产生任务
            var del_key_array = DBServerProvider.DbContext.Set<fk_reimtask>().Where(w => w.stepid == tostepid && w.reimid == (Guid)key.ToGuid() && w.ishandled != 1);
            DBServerProvider.DbContext.Set<fk_reimtask>().RemoveRange(del_key_array);//删除没有审核过的任务
            List<string> to_username = new List<string>();//本步骤任务领取的人员清单；
            //1、通过角色获取
            //var tousername_from_role = DBServerProvider.DbContext.Set<Sys_User>().Where(w => w.Role_Id == ff.roleid).Select(s=>s.UserName).ToList();//单角色
            if (tostepid == curr_stepid && tostepid == GetFirstStepid(entity))//如果是第一步只分配任务给自己
            {
                to_username.Add(userInfo.UserName);
            }
            else
            {
                var touserid_from_userrole = DBServerProvider.DbContext.Set<Sys_UserRole>().Where(w => w.RoleId == ff.roleid).Select(s => s.UserId).ToList();
                var tousername_from_role = DBServerProvider.DbContext.Set<Sys_User>().Where(w => touserid_from_userrole.Contains(w.User_Id)).Select(s => s.UserName).ToList();//多角色
                to_username = tousername_from_role;
            }
            // 当页面操作选择不同意时，到业务表中查询创建人id，将流程任务分配给这个人
            if (status == "不同意")
            {
                to_username.Clear();
                int CreateID = Convert.ToInt16(typeof(T).GetProperty("CreateID").GetValue(entity));
                var touserid_from_userrole = DBServerProvider.DbContext.Set<Sys_UserRole>().Where(w => w.UserId == CreateID).Select(s => s.UserId).ToList();
                var tousername_from_role = DBServerProvider.DbContext.Set<Sys_User>().Where(w => touserid_from_userrole.Contains(w.User_Id)).Select(s => s.UserName).ToList();//多角色
                to_username = tousername_from_role;
            }

            // 当页面操作选择回退时，需要到任务表中查询回退到的节点中有哪些人审批过。排除汇签的人
            if (status == "回退")
            {
                to_username.Clear();
                List<string> to_username1 =  DBServerProvider.DbContext.Set<fk_reimtask>().Where(x => x.stepid == tostepid && x.ishandled == 1 && x.reimid == key.ToGuid() && x.task_type != "汇签").Select(s => s.to_username).ToList();
                to_username1.ForEach(s => {
                    if (!to_username.Contains(s))
                    {
                        to_username.Add(s);
                    }
                });
            }

            for (int i = 0; i < to_username.Count; i++)
            {
                fk_reimtask fk_Reimtask = new fk_reimtask();
                fk_Reimtask.path_router = ff.path_router;
                if (ff.path_router == null) continue;
                fk_Reimtask.menuname = DBServerProvider.DbContext.Set<Sys_Menu>().Where(w => w.Url == ff.path_router).Select(s => s.MenuName).FirstOrDefault();
                fk_Reimtask.createtime = DateTime.Now;
                fk_Reimtask.to_username= to_username[i].Trim();
                var user = DBServerProvider.DbContext.Set<Sys_User>().Where(w => w.UserName == to_username[i].Trim()).FirstOrDefault();
                if (!string.IsNullOrEmpty(user.Email)) SendEmail(user.Email, "【产品定价流程】审批提醒", "【产品定价流程】请即时登录系统审批！<br>链接： <a href='http://10.100.8.241:9990/#/home'>产品定价流程系统</a>");
                fk_Reimtask.ishandled = 0;
                fk_Reimtask.to_userrealname = user.UserTrueName;
                fk_Reimtask.reimid = key.ToGuid();
                fk_Reimtask.stepid = tostepid;
                if (tostepid == 20 || tostepid == 70)//财务核准或者财务核价 发送邮件给艾玲
                {
                    string email = "ailing3@mychery.com";//
                    SendEmail(email, "【产品定价流程】审批提醒",  "【产品定价流程】<br>请即时登录系统审批!<br>链接： <a href='http://10.100.8.241:9990/#/home'>产品定价流程系统</a>");
                }
                // 如果下个节点为归档则该流程任务自动结束
                if (tostepid == 99)
                {
                    fk_Reimtask.ishandled = 1;
                    fk_Reimtask.reyijian = "同意";
                    fk_Reimtask.remark = "归档";
                    fk_Reimtask.handledtime = DateTime.Now;
                }
                fk_Reimtask.stepname= ff.stepname;
                fk_Reimtask.reimtable = workTable;
                DBServerProvider.DbContext.Add(fk_Reimtask);
            }
            DBServerProvider.DbContext.SaveChanges();

        }
        //根据属性名称获取属性值
        private static string GetPropertyValue<T>(T t, string field)
        {
            string value = "";
            if (t == null)
            {
                return value;
            }
            PropertyInfo[] properties = t.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);

            if (properties.Length <= 0)
            {
                return value;
            }
            var property = properties.Where(x => x.Name == field).FirstOrDefault();
            value = property.GetValue(t, null).ToString();

            return value;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="emailaddress"></param>
        /// <param name="title">审批提醒</param>
        /// <param name="content">请即时登录系统审批！</param>
        static void SendEmail(string emailaddress, string title, string content)
        {
            try
            {
                EmailHelper emailHelper = new EmailHelper(emailaddress, title, content);
                //emailHelper.AddAttachments(("wwwroot/" + dddx.fujian).MapPath());
                emailHelper.SendMailAsync();
            }
            catch (Exception)
            {
                Console.WriteLine("邮件发送失败");
            }
        }

    }
}
